package com.enki.cigarettes.controller;

import com.enki.cigarettes.entity.BalanceHistoryT;
import com.enki.cigarettes.entity.OrderT;
import com.enki.cigarettes.entity.RechargeRecordT;
import com.enki.cigarettes.entity.UserT;
import com.enki.cigarettes.enums.BalanceEnums;
import com.enki.cigarettes.enums.OrderEnums;
import com.enki.cigarettes.enums.RechargeEnums;
import com.enki.cigarettes.handler.Response;
import com.enki.cigarettes.repository.BalanceHistoryTRepository;
import com.enki.cigarettes.repository.OrderTRepository;
import com.enki.cigarettes.repository.RechargeRecordTRepository;
import com.enki.cigarettes.repository.UserTRepository;
import com.enki.cigarettes.utils.PrimaryKey;
import com.enki.cigarettes.utils.wechatpay.WXJSAPIPayConfigImpl;
import com.enki.cigarettes.utils.wechatpay.pay.sdk.WXPayConstants;
import com.enki.cigarettes.utils.wechatpay.pay.sdk.WXPayUtil;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.*;

/**
 * @author WCS.Wang
 * @version V1.0
 * @Package com.enki.cigarettes.controller
 * @Name e-cigarettes-shop-api-module
 * @Description: TODO 微信支付
 * @date 2019-07-21
 */
@RestController
@RequestMapping("/api/wechat")
@Slf4j
public class WechatPayController {

    private WXJSAPIPayConfigImpl wxjsapiPayConfig;

    public WechatPayController() throws Exception {
        wxjsapiPayConfig = WXJSAPIPayConfigImpl.getInstance();
    }

    @Autowired
    OrderTRepository orderTRepository;
    @Autowired
    RechargeRecordTRepository rechargeRecordTRepository;
    @Autowired
    UserTRepository userTRepository;
    @Autowired
    BalanceHistoryTRepository balanceHistoryTRepository;


    @ApiOperation(value = "订单支付异步通知")
    @RequestMapping(value = "/jsapi")
    public void responseOrder(HttpServletRequest request, HttpServletResponse response) {
        try {
            //读取参数
            InputStream inputStream;
            StringBuffer sb = new StringBuffer();
            inputStream = request.getInputStream();
            String s;
            BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
            while ((s = in.readLine()) != null) {
                sb.append(s);
            }
            in.close();
            inputStream.close();
            String xmlString = sb.toString();
            Map<String, String> resultData = WXPayUtil.xmlToMap(xmlString);
            // 1.通知参数
            String result_code = resultData.get("result_code");
            String return_code = resultData.get("return_code");
            String resXml = "";
            log.info("---------------------resultData---------------");
            System.out.println(resultData);
            log.info("---------------------resultData-end---------------");
            if (return_code.equals("SUCCESS") && result_code.equals("SUCCESS")) {
                // 2.获取签名信息
                if (WXPayUtil.isSignatureValid(resultData, wxjsapiPayConfig.getKey())) {
                    // 3.处理支付结果
                    // 商户订单号
                    String out_trade_no = resultData.get("out_trade_no");
                    // 微信支付订单号
                    String transaction_id = resultData.get("transaction_id").toString();
                    // TODO 处理支付结果
                    List<OrderT> orderItems = orderTRepository.findByOrderPaymenId(out_trade_no);
                    List<OrderT> updateOrderItems = new ArrayList<>();
                    for (OrderT order : orderItems) {
                        // 更新订单状态
                        order.setOrderStatus(OrderEnums.OrderStatus.PAID.getStatus());
                        updateOrderItems.add(order);
                    }
                    orderTRepository.saveAll(updateOrderItems);
                    resXml = setXml(WXPayConstants.SUCCESS, "OK");
                } else {
                    resXml = setXml(WXPayConstants.FAIL, "签名失败");
                }
            } else {
                resXml = setXml(WXPayConstants.FAIL, "参数格式校验错误");
            }
            BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
            out.write(resXml.getBytes());
            out.flush();
            out.close();
        } catch (Exception e) {
            log.error("处理支付结果失败：" + e.getMessage());
            e.printStackTrace();
        }
    }


    @ApiOperation(value = "处理充值异步通知")
    @RequestMapping(value = "/recharge")
    @Transactional
    public void responseRecharge(HttpServletRequest request, HttpServletResponse response) {
        try {
            //读取参数
            InputStream inputStream;
            StringBuffer sb = new StringBuffer();
            inputStream = request.getInputStream();
            String s;
            BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
            while ((s = in.readLine()) != null) {
                sb.append(s);
            }
            in.close();
            inputStream.close();
            String xmlString = sb.toString();
            Map<String, String> resultData = WXPayUtil.xmlToMap(xmlString);
            // 1.通知参数
            String result_code = resultData.get("result_code");
            String return_code = resultData.get("return_code");
            String resXml = "";
            log.info("---------------------resultData---------------");
            System.out.println(resultData);
            log.info("---------------------resultData-end---------------");
            if (return_code.equals("SUCCESS") && result_code.equals("SUCCESS")) {
                // 2.获取签名信息
                if (WXPayUtil.isSignatureValid(resultData, wxjsapiPayConfig.getKey())) {
                    // 3.处理支付结果
                    // 商户订单号
                    String out_trade_no = resultData.get("out_trade_no");
                    // 微信支付订单号
                    String transaction_id = resultData.get("transaction_id");
                    // 处理支付结果
                    RechargeRecordT rechargeRecord = rechargeRecordTRepository.findFirstById(out_trade_no);
                    if (rechargeRecord != null) {
                        rechargeRecord.setTransactionId(transaction_id);
                        rechargeRecord.setStatus(RechargeEnums.RechargeStatus.SUCCESS.getStatus());
                        rechargeRecord.setPayTime(new Date());
                        // 余额变化，金额单位为分
                        // 处理用户余额
                        UserT userBean = userTRepository.findOneById(rechargeRecord.getUserTId());
                        if (userBean != null) {
                            int rechargeAmount = rechargeRecord.getAmount() + rechargeRecord.getAmount();
                            int curBalance = userBean.getCurBalance() + rechargeAmount;
                            userBean.setCurBalance(curBalance);
                            // 记录余额变化历史
                            BalanceHistoryT balanceHistory = new BalanceHistoryT();
                            balanceHistory.setId(PrimaryKey.get().toString());
                            balanceHistory.setBalanceAmountTotal(curBalance);
                            balanceHistory.setBalanceStatus(BalanceEnums.BalanceStatus.SIGN_IN.getStatus());
                            balanceHistory.setSubTotal(rechargeAmount);
                            balanceHistory.setUserTId(userBean.getId());
                            balanceHistory.setRemark("来自订单" + out_trade_no + "充值");
                            balanceHistory.setCreateTime(new Date());
                            rechargeRecordTRepository.save(rechargeRecord);
                            userTRepository.save(userBean);
                            balanceHistoryTRepository.save(balanceHistory);
                        }
                    }
                    resXml = setXml(WXPayConstants.SUCCESS, "OK");
                } else {
                    resXml = setXml(WXPayConstants.FAIL, "签名失败");
                }
            } else {
                resXml = setXml(WXPayConstants.FAIL, "参数格式校验错误");
            }
            BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
            out.write(resXml.getBytes());
            out.flush();
            out.close();
        } catch (Exception e) {
            log.error("处理支付结果失败：" + e.getMessage());
            e.printStackTrace();
        }
    }


    /**
     * 通过xml 发给微信消息
     *
     * @param return_code
     * @param return_msg
     * @return
     */
    public static String setXml(String return_code, String return_msg) {
        SortedMap<String, String> parameters = new TreeMap<>();
        parameters.put("return_code", return_code);
        parameters.put("return_msg", return_msg);
        return "<xml><return_code><![CDATA[" + return_code + "]]></return_code><return_msg><![CDATA[" + return_msg + "]]></return_msg></xml>";

    }


}
